/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.    
*/


/* Name
' ODBC Connection
' Matthew Tuffin 24/08/2007
' Desc
 * Communicate with ODBC Providers. ie. FoxPro
'
' Requirements:
 * System.Data 
 * System.Collections
 * System.Windows.Forms
 * System.Data.SqlClient
 * System.Collections;
 * System.Collections.Generic;
 * Logger
'
' Usage:
 * Create a new object from this class. The default constructor is not supported. You have to create a connectionstring
 * either through the builder or supply one
'
' Limitations:
 * 
'
*/

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Odbc;
using System.Data.Common;
using System.Windows.Forms;
using System.Collections;

namespace DBConnection
{
    /// <summary>
    /// ODBCConnection class for things like foxpro
    /// </summary>
    public class ODBCConnection : IDBSourceConnection
    {
        //Local pointer to ConnStringBuilder
        private OdbcConnectionStringBuilder mp_ConnStringBuilder;
        //local pointer to Connection
        private OdbcConnection mp_SQLDBConn;
        //local pointer to CommandBuilder
        private OdbcCommandBuilder mp_SQLCommandBuilder;
   
        /// <summary>
        /// Default Constructor is not supported
        /// </summary>
        public ODBCConnection() : base ()
        {
            try
            {
                throw (new Exception("Can not create connection with out connection string"));
            }
            catch (Exception ex)
            {
                CMsgBox.ShowMsgBox(ex.Message);
                Application.Exit();
            }
        }

        /// <summary>
        /// Constructor that accepts a connection string
        /// </summary>
        /// <param name="strConnectionString">Connection String</param>
        public ODBCConnection(string strConnectionString)
            : base(strConnectionString)
        {
            SetConnBuilder();
            m_strlocalConnString = mp_ConnStringBuilder.ConnectionString;
            SetConnection(mp_ConnStringBuilder.ConnectionString);
            SetCommandBuilder();
        }

        /// <summary>
        /// Construtor with a datasource and database specified
        /// </summary>
        /// <param name="strDriver">Driver</param>
        /// <param name="strDSN">DSN</param>
        public ODBCConnection(string strDriver, string strDSN)
        {
            SetConnBuilder();
            SetConnectionProperties(strDriver, strDSN);
            m_strlocalConnString = mp_ConnStringBuilder.ConnectionString;
            SetCommandBuilder();
        }

        /// <summary>
        /// Creates a new SQLConnection Object
        /// </summary>
        /// <param name="strConnString">Connection String</param>
        private void SetConnection(string strConnString)
        {
            base.SetConnection(typeof(System.Data.Odbc.OdbcConnection), strConnString);
            mp_SQLDBConn = (OdbcConnection)m_DBConnection;
        }

        /// <summary>
        /// Creates a new SQLConnectionBuilder
        /// </summary>
        private void SetConnBuilder()
        {
            base.SetConnBuilder(typeof(System.Data.Odbc.OdbcConnectionStringBuilder));
            mp_ConnStringBuilder = (OdbcConnectionStringBuilder)m_DBConnStringBuilder;
        }

        /// <summary>
        /// Creates a new SQLCommandBuilder
        /// </summary>
        private void SetCommandBuilder()
        {
            base.SetCommandBuilder(typeof(System.Data.Odbc.OdbcCommandBuilder));
            mp_SQLCommandBuilder = (OdbcCommandBuilder)m_DBCommandBuilder;
        }

        /// <summary>
        /// Sets the Connection Properties in ConnStringBuilder
        /// </summary>
        /// <param name="strDriver">Driver</param>
        /// <param name="strDSN">DSN</param>        
        public void SetConnectionProperties(string strDriver, string strDSN)
        {
            mp_ConnStringBuilder.Driver = strDriver;
            mp_ConnStringBuilder.Dsn = strDSN;
            SetConnection(mp_ConnStringBuilder.ConnectionString);
        }
        
        /// <summary>
        /// Exeception Message for ODBC Connections
        /// </summary>
        /// <param name="ee">Exception</param> 
        public override void SQLExceptionMessageBox(DbException ee)
        {
            string errorMessage;
            OdbcException ex = (OdbcException)ee;

            for (int i = 0; i < ex.Errors.Count; i++)
            {
                errorMessage = ("Index #" + i + "\n" +
                    "Message: " + ex.Errors[i].Message + "\n" +
                    "NativeError: " + ex.Errors[i].NativeError + "\n" +
                    "Source: " + ex.Errors[i].Source + "\n" +
                    "SQLState: " + ex.Errors[i].SQLState + "\n");

                CMsgBox.ShowMsgBox(errorMessage);
            }
        }


        /// <summary>
        /// Requests a sqldatareader given a query
        /// </summary>
        /// <param name="strQuery">Select Query</param>
        /// <returns>sqlDataReader</returns>
        public OdbcDataReader RequestReader(string strQuery)
        {
            OdbcDataReader Reader = (OdbcDataReader)ReadSQLIntoDataReader(strQuery);
            return Reader;
        }

        /// <summary>
        /// Requests a datatable using a new adapter
        /// </summary>
        /// <param name="strQuery">Select Query</param>
        /// <param name="strAdapterName">New AdapterName</param>
        /// <returns>DataTable</returns>
        public override DataTable RequestDataTableUsingSQLAdapter(string strQuery, string strAdapterName)
        {
            OdbcDataAdapter sqlAdapter;
            SetAdapter(typeof(System.Data.Odbc.OdbcDataAdapter), strAdapterName);
            DataTable DT = SelectSQLIntoDataTable(strQuery, strAdapterName);
            sqlAdapter = (OdbcDataAdapter)m_DictionaryDataAdapters[strAdapterName];

            sqlAdapter.RowUpdating += new OdbcRowUpdatingEventHandler(sqlAdapter_RowUpdating);
            sqlAdapter.RowUpdated += new OdbcRowUpdatedEventHandler(sqlAdapter_RowUpdated);
            return (DT);
        }

        /// <summary>
        /// RowUpdated Event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void sqlAdapter_RowUpdated(object sender, OdbcRowUpdatedEventArgs e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        /// <summary>
        /// RowUpdating Event
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void sqlAdapter_RowUpdating(object sender, OdbcRowUpdatingEventArgs e)
        {
            //throw new Exception("The method or operation is not implemented.");
        }

        /// <summary>
        /// Add a Parameter to an ODBCCommand please note parameters are denoted by ? and its position in the parameter collection that is important 
        /// </summary>
        /// <param name="Command">Command</param>
        /// <param name="strParameterName">ParameterName</param>
        /// <param name="DBType">DataType</param>
        /// <param name="ParDir">ParameterDirection enum</param>
        /// <param name="iSizeData">Size of the Data</param>
        /// <param name="RowVersion">Which Version of the row DataRowVersion enum</param>
        public void AddParameterToSQLCommand(OdbcCommand Command, string strParameterName, DbType DBType,
                                            ParameterDirection ParDir, int iSizeData, DataRowVersion RowVersion)
        {
            OdbcParameter parameter = (OdbcParameter)CreateNewParameter(typeof(System.Data.Odbc.OdbcParameter));
            parameter.ParameterName = strParameterName;
            parameter.DbType = DBType;
            parameter.Direction = ParDir;
            parameter.Size = iSizeData;
            parameter.SourceVersion = RowVersion;
            Command.Parameters.Add(parameter);
        }
    }
}
